/* Copyright (C) 2008, 2009, 2010 Faindu GmbH, Switzerland.
* All Rights Reserved. The following is Source Code and is subject to all restrictions 
* on such code as contained in the license accompanying this project. */
package blocstac.editimage.rotate
{

import blocstac.editimage.base.Control;
import blocstac.editimage.base.ImageOperation;
import blocstac.editimage.base.StateManager;
import blocstac.editimage.base.ViewModel;

import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;

/**
 * The user drags these "buttons" to edit the image.
 */
public class RotateTool extends Control
{
	private var _rotateComponent:Sprite
	
	function RotateTool(stateManager:StateManager, rotateComponent:Sprite) {
		super(stateManager)
		_rotateComponent = rotateComponent
	}
	
	//--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------
	private static const ROTATION_STEP:Number = 15/180 * Math.PI
	private static const LENGTH:Number = 20 
	private static const CONTROL_SIZE:Number = 30
	private static const HALF_CONTROL_SIZE:Number = CONTROL_SIZE/2;

	[Embed(source="/blocstac/editimage/assets/RotateCircle.swf", symbol="ScaleCircle")]
	private var RotateCircle:Class;
	
	private var _circle:DisplayObject
	private var _imageCenterOnStage:Point
	private var _initialAngle:Number
	private var _operation:ImageOperation
	
	/** @inheritDoc */
	override protected function draw(event:Event=null): void 
	{
		super.draw()
		
		var g:Graphics = graphics
		g.clear()
		
		// draw connecting line
		g.lineStyle(2, 0)
		g.lineTo(0, LENGTH)
		
		// invisible square for larger mouse target
  		g.moveTo(0, 0)
  		g.lineStyle()							
		g.beginFill(0xff0000, 0)
		g.drawRect(-HALF_CONTROL_SIZE, 0, CONTROL_SIZE, LENGTH)
		g.endFill() 
	}

	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------
	override public function init(toolsComponent:Sprite): void {
		_circle = new RotateCircle()
		addChild(_circle)
		cursor = new RotateCursor()
		update()
		addEventListener(MouseEvent.CLICK, clickCanceler)
		
		super.init(toolsComponent)
	}

	
	private function clickCanceler(event:MouseEvent):void {
		event.stopImmediatePropagation()
	}
		
	override protected function startInteractionHandler(mouseEvent:MouseEvent):void {
		if (stateManager.interactionStarts()) {
			var viewModel:ViewModel = stateManager.viewModel
			_initialAngle = viewModel.angle
			var rotationCompToStageMatrix:Matrix = _rotateComponent.transform.concatenatedMatrix
			_imageCenterOnStage = rotationCompToStageMatrix.transformPoint(viewModel.imageCenterInImageComp)
			stage.addEventListener(MouseEvent.MOUSE_MOVE, interaction)
			stage.addEventListener(MouseEvent.MOUSE_UP, endInteractionHandler)
			stage.addEventListener(Event.MOUSE_LEAVE, endInteractionOutsideHandler)
		}
	}
	
	private function interaction(mouseEvent:MouseEvent):void {
		_operation = createOp(mouseEvent.stageX, mouseEvent.stageY, mouseEvent.shiftKey, _initialAngle)
		stateManager.apply(_operation)
	}
	
	private function endInteractionOutsideHandler(event:Event):void {
		endInteraction(_operation)
	}
	
	private function endInteractionHandler(mouseEvent:MouseEvent):void {
		var op:ImageOperation = createOp(mouseEvent.stageX, mouseEvent.stageY, mouseEvent.shiftKey, _initialAngle)
		endInteraction(op)
	}
	
	private function endInteraction(op:ImageOperation):void {
		stage.removeEventListener(MouseEvent.MOUSE_MOVE, interaction)
		stage.removeEventListener(MouseEvent.MOUSE_UP, endInteractionHandler)
		stage.removeEventListener(Event.MOUSE_LEAVE, endInteractionOutsideHandler)
		
		stateManager.interactionEnds(op)
		
		_imageCenterOnStage = null
	}
	
	internal function createOp(mouseStageX:Number, mouseStageY:Number, shiftKey:Boolean, initialAngle:Number=0):ImageOperation {
		var globalMouseLocation:Point = new Point(mouseStageX, mouseStageY)
		var offset:Point = globalMouseLocation.subtract(_imageCenterOnStage)
		var finalAngle:Number =  Math.atan2(offset.y, offset.x) + Math.PI/2
		if (shiftKey) {
			return new RotateOperation(initialAngle, finalAngle)
		} else {
			var steppedFinalAngle:Number = Math.round( finalAngle / ROTATION_STEP ) * ROTATION_STEP
			return new RotateOperation(initialAngle, steppedFinalAngle)
		}
	}
	
	public function update():void {
		x = stateManager.viewModel.imageViewWidth * 0.5
		y = - LENGTH
	}
	
}
}